#include "mcp_decode.h"
#include <stdio.h>
#include "mcp_logger.h"
#include "mcp_encrypt.h"
#include <pthread.h>
#include "mcp_logger.h"

// 加密的key
const char* encryption_key = "mcp_protocol_2025";

// 当前保存的序列号的值
static uint16_t sequence_number = 0;
// 取序列号的同步锁
static pthread_mutex_t sequence_mutex = PTHREAD_MUTEX_INITIALIZER;
// 0/1 未初始化/初化
static int initialized = 0;

/**
 * 取下一个序列号
 * @return
 */
uint16_t get_next_sequence(void) {
    uint16_t next_seq;

    pthread_mutex_lock(&sequence_mutex);

    // 第一次调用时初始化, 随机生成一个数
    if (!initialized) {
        sequence_number = (uint16_t)(rand() % 65535 + 1);
        initialized = 1;
    }

    // 递增序列号
    if (sequence_number == UINT16_MAX) {
        sequence_number = 1;
        next_seq = 1;
    } else {
        next_seq = ++sequence_number;
    }

    pthread_mutex_unlock(&sequence_mutex);

    return next_seq;
}

/**
 * CRC16 校验
 */
uint16_t calculate_crc16(const uint8_t* data, uint16_t length) {
    uint16_t crc = 0xFFFF;
    for (uint16_t i = 0; i < length; i++) {
        crc ^= data[i];
        for (uint8_t j = 0; j < 8; j++) {
            if (crc & 0x0001) {
                crc = (crc >> 1) ^ 0xA001;
            } else {
                crc = crc >> 1;
            }
        }
    }
    return crc;
}

/**
 * 生成消息内容数据包
 */
int create_packet_data(uint8_t encrypt, uint8_t protocol, uint16_t sequence, const char* message,
                uint8_t* output, uint16_t* output_length) {
    if (!output || !output_length || !message) {
        LOG_ERROR(">>>>>> Error create_packet_data: param is empty");
        return -1;
    }

    // 构建完整数据包
    int pos = 0;

    // 写入是否加密
    output[pos++] = encrypt;
    // 写入对应协议号，响应时
    output[pos++] = protocol;
    // 写入对应序列号，响应时
    output[pos++] = (sequence >> 8) & 0xFF;
    output[pos++] = sequence & 0xFF;

    // 对 JSON 字符串加密
    if (encrypt == 0x01) {
        // 加密
        char *encrypt_message = mcp_encrypt(message, encryption_key);
        if (!encrypt_message) {
            LOG_ERROR(">>>>>> Error create_packet_data: encrypt exception!");
            return -3;
        }
        // LOG_DEBUG(">>>>>> Encrypted content: %s",encrypt_message);

        // 内容长度
        uint16_t data_length = (uint16_t)strlen(encrypt_message);
        if (pos + data_length > MAX_PACKET_SIZE - 12) {
            LOG_ERROR(">>>>>> Error create_packet_data: The data packet exceeds the max length %dd!",pos + data_length);
            free(encrypt_message);
            return -2;
        }

        memcpy(output + pos, encrypt_message, data_length);
        pos += data_length;
        free(encrypt_message);  // 释放加密数据
    } else {
        // 不加密
        uint16_t data_length = (uint16_t)strlen(message);
        if (pos + data_length > MAX_PACKET_SIZE - 12) {
            LOG_ERROR(">>>>>> Error create_packet_data: The data packet exceeds the max length %dd!",pos + data_length);
            return -2;
        }

        memcpy(output + pos, message, data_length);
        pos += data_length;
    }

    *output_length = pos;
    return 0;
}

/**
 * 生成网络传输数据包
 */
int create_packet(uint8_t protocol, uint8_t version, const char* message, uint16_t sequence,
                  uint8_t encrypt, uint8_t resp_protocol, uint16_t resp_sequence,
                  uint8_t* output, uint16_t* output_length) {
    if (!output || !output_length) {
        LOG_ERROR(">>>>>> Error create_packet: param is empty");
        return -1;
    }

    // 数据打包
    uint8_t pack_data[MAX_PACKET_SIZE];
    uint16_t data_length = 0;

    if (message) {
        int ret = create_packet_data(encrypt, resp_protocol, resp_sequence, message, pack_data, &data_length);
        if (ret != 0) {
            return ret + -3;
        }
    }

    // 计算总长度 = 起始位(2) + 长度(2) + 协议号(1) + 版本号(1) + 数据(n) + 序列号(2) + 校验和(2) + 停止位(2)
    uint16_t total_length = 2 + 2 + 1 + 1 + data_length + 2 + 2 + 2;
    if (total_length > MAX_PACKET_SIZE) {
        return -2;
    }

    // 准备校验和数据: length(2) + protocol(1) + version(1) + data(n) + sequence(2)
    uint8_t checksum_data[MAX_PACKET_SIZE];
    uint16_t pos = 0;

    // 写入长度, 大端字节序
    checksum_data[pos++] = (data_length >> 8) & 0xFF;
    checksum_data[pos++] = data_length & 0xFF;

    // 写入协议号
    checksum_data[pos++] = protocol;

    // 写入版本号
    checksum_data[pos++] = version;

    // 写入数据包(校验码包含数据包)
    if (data_length > 0) {
        memcpy(checksum_data + pos, pack_data, data_length);
        pos += data_length;
    }

    // 写入序列号
    if (sequence == 0) {
        sequence = get_next_sequence();
    }
    checksum_data[pos++] = (sequence >> 8) & 0xFF;
    checksum_data[pos++] = sequence & 0xFF;

    // 计算校验和
    uint16_t checksum = calculate_crc16(checksum_data, pos);

    // 构建完整数据包
    pos = 0;

    // 起始位
    output[pos++] = (START_BYTES >> 8) & 0xFF;
    output[pos++] = START_BYTES & 0xFF;

    // 数据长度 大端字节序
    output[pos++] = (data_length >> 8) & 0xFF;
    output[pos++] = data_length & 0xFF;

    // 协议号
    output[pos++] = protocol;

    // 版本号
    output[pos++] = version;

    // 消息内容
    if (data_length > 0) {
        memcpy(output + pos, pack_data, data_length);
        pos += data_length;
    }

    // 序列号
    output[pos++] = (sequence >> 8) & 0xFF;
    output[pos++] = sequence & 0xFF;

    // 校验位
    output[pos++] = (checksum >> 8) & 0xFF;
    output[pos++] = checksum & 0xFF;

    // 停止位
    output[pos++] = (END_BYTES >> 8) & 0xFF;
    output[pos++] = END_BYTES & 0xFF;

    *output_length = pos;
    return 0;
}

/**
 * 解析数据包内容
 */
int parse_packet_data(const uint8_t* data, uint16_t data_length, uint8_t* encrypt,
                     uint8_t* resp_protocol, uint16_t* resp_sequence, char** message) {
    if (!data || data_length < 4 || !encrypt || !resp_protocol || !resp_sequence || !message) {
        return -1;
    }

    // 消息体结构：encrypt(1) + protocol(1) + sequence(2) + data(data_length-4)
    // LOG_DEBUG("<<<<<< Body content HEX: %s",bytes_to_hex((char*)data,data_length));

    // 解析数据包头
    uint8_t encrypt1 = data[0];
    uint8_t protocol = data[1];
    uint16_t sequence = (data[2] << 8) | data[3];

    int pos = 4;
    // LOG_DEBUG("<<<<<< Body structure: protocol=0x%02X, encryption_key=%s, sequence=%d\n", protocol, encryption_key, sequence);

    // 剩余的数据长度
    uint16_t content_length = data_length - 4;

    if (content_length > 0) {
        if (encrypt1 == 0x01) {
            // 需要解密
            // 注意：加密后的数据是Base64编码的字符串，需要以null结尾
            char* encrypted_data = (char*)malloc(content_length + 1);
            if (!encrypted_data) {
                return -2;
            }
            memcpy(encrypted_data, data + pos, content_length);
            encrypted_data[content_length] = '\0';

            // LOG_DEBUG("<<<<<< Before decryption: %s",bytes_to_hex((char*)encrypted_data,content_length));

            *message = mcp_decrypt(encrypted_data, encryption_key);
            // LOG_DEBUG("<<<<<< After decryption: %s",bytes_to_hex((char*)message,content_length));

            free(encrypted_data);

            if (!*message) {
                return -3;
            }
        } else {
            // 不加密，直接复制
            *message = (char*)malloc(content_length + 1);
            if (!*message) {
                return -2;
            }
            memcpy(*message, data + pos, content_length);
            (*message)[content_length] = '\0';
        }
    } else {
        *message = NULL;
    }

    *encrypt = encrypt1;
    *resp_protocol = protocol;
    *resp_sequence = sequence;

    return 0;
}

/**
 * 解析数据流
 */
int parse_packet(const uint8_t* input, uint16_t input_length, CustomPacket* packet) {
    if (!input || !packet || input_length < 12) { // 最小包头长度
        return -1;
    }
    // 检查起始位 0xff 0x55
    uint16_t start = (input[0] << 8) | input[1];
    if (start != START_BYTES) {
        return -2;
    }

    // 读取数据长度
    uint16_t data_length = (input[2] << 8) | input[3];

    // 检查数据包完整性;
    uint16_t expected_length = 2 + 2 + 1 + 1 + data_length + 2 + 2 + 2; // 完整包长度
    if (input_length < expected_length) {
        return -3;
    }

    // 读取协议号
    uint8_t protocol = input[4];

    // 读取版本号
    uint8_t version = input[5];

    // 读取消息内容
    const uint8_t* message_data = input + 6;

    // 读取序列号
    uint16_t sequence = (input[6 + data_length] << 8) | input[7 + data_length];

    // 读取校验位
    uint16_t checksum = (input[8 + data_length] << 8) | input[9 + data_length];

    // 检查停止位
    uint16_t end = (input[10 + data_length] << 8) | input[11 + data_length];
    if (end != END_BYTES) {
        return -4;
    }

    // 验证校验和: length(2) + protocol(1) + version(1) + data(n) + sequence(2)
    uint8_t verify_data[MAX_PACKET_SIZE];
    uint16_t pos = 0;

    // 数据长度
    verify_data[pos++] = (data_length >> 8) & 0xFF;
    verify_data[pos++] = data_length & 0xFF;

    // 协议号
    verify_data[pos++] = protocol;

    // 版本号
    verify_data[pos++] = version;

    // 消息内容
    memcpy(verify_data + pos, message_data, data_length);
    pos += data_length;

    // 序列号
    verify_data[pos++] = (sequence >> 8) & 0xFF;
    verify_data[pos++] = sequence & 0xFF;

    uint16_t calculated_checksum = calculate_crc16(verify_data, pos);
    if (calculated_checksum != checksum) {
        return -5;
    }

    // 填充packet结构
    packet->protocol = protocol;
    packet->version = version;
    packet->sequence = sequence;
    packet->data_length = data_length;

    if (data_length > 0) {
        packet->data = malloc(data_length);
        if (!packet->data) {
            return -6;
        }
        memcpy(packet->data, message_data, data_length);
    } else {
        packet->data = NULL;
    }

    return 0;
}

void free_packet(CustomPacket* packet) {
    if (packet && packet->data) {
        free(packet->data);
        packet->data = NULL;
    }
}

// 编码示例
void encode_example() {
    uint8_t output[MAX_PACKET_SIZE];
    uint16_t output_length;
    const char* message = "{\"id\": \"123\", \"cmd\": \"test\"}";

    int ret = create_packet(0x01, 0x01, message, 1001, 0x01, 0x02, 2001, output, &output_length);
    if (ret == 0) {
        LOG_DEBUG(">>>>>> Encoding successful. Data packet length: %d\n", output_length);
    }
}

// 解码示例
void decode_example(const uint8_t* input, uint16_t input_length) {
    CustomPacket packet;

    int ret = parse_packet(input, input_length, &packet);
    if (ret == 0) {
        LOG_DEBUG("<<<<<< Decoding successful: protocol=%d, version=%d, sequence=%d\n",packet.protocol, packet.version, packet.sequence);

        // 解析数据内容
        uint8_t encrypt;
        uint8_t resp_protocol;
        uint16_t resp_sequence;
        char* message;

        ret = parse_packet_data(packet.data, packet.data_length, &encrypt,
                               &resp_protocol, &resp_sequence, &message);
        if (ret == 0) {
            LOG_DEBUG("<<<<<< content: encrypt=%d, resp_protocol=%d, resp_sequence=%d, message=%s\n",
                   encrypt, resp_protocol, resp_sequence, message);
            free(message);
        }

        free_packet(&packet);
    }
}